Tutustu edistyneeseen micro-frontend-arkkitehtuuriin käyttämällä JavaScript Module Federationia ja Webpack 5:tä. Opi rakentamaan skaalautuvia ja ylläpidettäviä sovelluksia.
JavaScript Module Federation ja Webpack 5: Edistynyt Micro-Frontend-arkkitehtuuri
Nykypäivän nopeasti kehittyvässä web-kehityksen maailmassa suurten ja monimutkaisten sovellusten rakentaminen voi olla merkittävä haaste. Perinteiset monoliittiset arkkitehtuurit johtavat usein koodikantoihin, joita on vaikea ylläpitää, skaalata ja julkaista. Micro-frontendit tarjoavat houkuttelevan vaihtoehdon pilkkomalla nämä suuret sovellukset pienemmiksi, itsenäisesti julkaistaviksi yksiköiksi. JavaScript Module Federation, Webpack 5:ssä esitelty tehokas ominaisuus, tarjoaa elegantin ja tehokkaan tavan toteuttaa micro-frontend-arkkitehtuureja.
Mitä ovat Micro-Frontendit?
Micro-frontendit edustavat arkkitehtuurista lähestymistapaa, jossa yksi web-sovellus koostuu useista pienemmistä, itsenäisistä sovelluksista. Jokainen micro-frontend voidaan kehittää, julkaista ja ylläpitää erillisten tiimien toimesta, mikä mahdollistaa suuremman autonomian ja nopeammat iteraatiosyklit. Tämä lähestymistapa heijastaa mikropalveluiden periaatteita backend-maailmassa, tuoden vastaavia etuja front-endiin.
Micro-frontendien keskeiset ominaisuudet:
- Itsenäinen julkaistavuus: Jokainen micro-frontend voidaan julkaista itsenäisesti vaikuttamatta sovelluksen muihin osiin.
- Teknologinen monimuotoisuus: Eri tiimit voivat valita tarpeisiinsa parhaiten sopivat teknologiat ja viitekehykset, mikä edistää innovaatiota ja mahdollistaa erikoisosaamisen käytön.
- Autonomiset tiimit: Jokainen micro-frontend on omistettu omalle tiimilleen, mikä edistää omistajuutta ja vastuullisuutta.
- Eristäminen: Micro-frontendien tulisi olla eristettyjä toisistaan riippuvuuksien minimoimiseksi ja ketjureaktioina tapahtuvien virheiden estämiseksi.
Esittelyssä JavaScript Module Federation
Module Federation on Webpack 5:n ominaisuus, joka mahdollistaa JavaScript-sovellusten dynaamisen koodin ja riippuvuuksien jakamisen ajon aikana. Se antaa eri sovelluksille (tai micro-frontendeille) mahdollisuuden paljastaa ja käyttää moduuleja toisiltaan, luoden käyttäjälle saumattoman integraatiokokemuksen.
Module Federationin keskeiset käsitteet:
- Host (isäntä): Isäntäsovellus on pääsovellus, joka orkestroi micro-frontendit. Se käyttää etäsovellusten paljastamia moduuleja.
- Remote (etäsovellus): Etäsovellus on micro-frontend, joka paljastaa moduuleja muiden sovellusten (mukaan lukien isännän) käytettäväksi.
- Shared Modules (jaetut moduulit): Moduulit, joita sekä isäntä- että etäsovellukset käyttävät. Webpack voi optimoida nämä jaetut moduulit estääkseen päällekkäisyyksiä ja pienentääkseen paketin kokoa.
Module Federationin käyttöönotto Webpack 5:llä
Module Federationin toteuttamiseksi sinun on määritettävä Webpack sekä isäntä- että etäsovelluksissa. Tässä on vaiheittainen opas:
1. Asenna Webpack ja siihen liittyvät riippuvuudet:
Varmista ensin, että sinulla on Webpack 5 ja tarvittavat lisäosat asennettuna sekä isäntä- että etäprojekteissasi.
npm install webpack webpack-cli webpack-dev-server --save-dev
2. Määritä isäntäsovellus:
Lisää isäntäsovelluksen webpack.config.js-tiedostoon ModuleFederationPlugin:
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const path = require('path');
module.exports = {
mode: 'development',
devtool: 'source-map',
entry: './src/index',
output: {
publicPath: 'http://localhost:3000/',
},
devServer: {
port: 3000,
hot: true,
historyApiFallback: true, // For single page application routing
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react']
}
}
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
},
plugins: [
new ModuleFederationPlugin({
name: 'Host',
filename: 'remoteEntry.js',
remotes: {
// Määritä etäsovellukset täällä, esim. 'RemoteApp': 'RemoteApp@http://localhost:3001/remoteEntry.js'
'RemoteApp': 'RemoteApp@http://localhost:3001/remoteEntry.js'
},
shared: {
react: { singleton: true, requiredVersion: '^17.0.0' },
'react-dom': { singleton: true, requiredVersion: '^17.0.0' },
// Lisää muut jaetut riippuvuudet tähän
},
}),
// ... muut lisäosat
],
};
Selitys:
name: Isäntäsovelluksen nimi.filename: Tiedoston nimi, joka paljastaa isännän moduulit. TyypillisestiremoteEntry.js.remotes: Kartoitus etäsovellusten nimistä niiden URL-osoitteisiin. Muoto on{EtäSovelluksenNimi: 'EtäSovelluksenNimi@URL/remoteEntry.js'}.shared: Luettelo moduuleista, jotka tulisi jakaa isäntä- ja etäsovellusten välillä.singleton: true-asetuksen käyttäminen varmistaa, että jaetusta moduulista ladataan vain yksi instanssi.requiredVersion-määrittely auttaa välttämään versioristiriitoja.
3. Määritä etäsovellus:
Määritä vastaavasti etäsovelluksen webpack.config.js:
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const path = require('path');
module.exports = {
mode: 'development',
devtool: 'source-map',
entry: './src/index',
output: {
publicPath: 'http://localhost:3001/',
},
devServer: {
port: 3001,
hot: true,
historyApiFallback: true, // For single page application routing
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react']
}
}
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
},
plugins: [
new ModuleFederationPlugin({
name: 'RemoteApp',
filename: 'remoteEntry.js',
exposes: {
'./Widget': './src/Widget',
// Lisää muut paljastetut moduulit tähän
},
shared: {
react: { singleton: true, requiredVersion: '^17.0.0' },
'react-dom': { singleton: true, requiredVersion: '^17.0.0' },
// Lisää muut jaetut riippuvuudet tähän
},
}),
// ... muut lisäosat
],
};
Selitys:
name: Etäsovelluksen nimi.filename: Tiedoston nimi, joka paljastaa etäsovelluksen moduulit.exposes: Kartoitus moduulien nimistä niiden tiedostopolkuihin etäsovelluksessa. Tämä määrittelee, mitkä moduulit ovat muiden sovellusten käytettävissä. Esimerkiksi'./Widget': './src/Widget'paljastaaWidget-komponentin, joka sijaitsee tiedostossa./src/Widget.js.shared: Sama kuin isäntäsovelluksen määrityksissä.
4. Luo paljastettava moduuli etäsovelluksessa:
Luo etäsovellukseen moduuli, jonka haluat paljastaa. Luo esimerkiksi tiedosto nimeltä src/Widget.js:
import React from 'react';
const Widget = () => {
return (
Etä-Widget
Tämä on widget RemoteApp-sovelluksesta.
);
};
export default Widget;
5. Käytä etämoduulia isäntäsovelluksessa:
Tuo etämoduuli isäntäsovellukseen dynaamisella tuonnilla. Tämä varmistaa, että moduuli ladataan ajon aikana.
import React, { useState, useEffect } from 'react';
const RemoteWidget = React.lazy(() => import('RemoteApp/Widget'));
const App = () => {
const [isWidgetLoaded, setIsWidgetLoaded] = useState(false);
useEffect(() => {
setIsWidgetLoaded(true);
}, []);
return (
Isäntäsovellus
Tämä on isäntäsovellus.
{isWidgetLoaded ? (
Ladataan Widget... }>
) : (
Ladataan...
)}
Selitys:
React.lazy(() => import('RemoteApp/Widget')): Tämä tuo dynaamisestiWidget-moduulinRemoteApp-sovelluksesta.RemoteApp-nimi vastaa isännän Webpack-määritystenremotes-osiossa määriteltyä nimeä.Widgetvastaa etäsovelluksen Webpack-määritystenexposes-osiossa määriteltyä moduulin nimeä.React.Suspense: Tätä käytetään etämoduulin asynkronisen latauksen käsittelyyn.fallback-ominaisuus määrittää komponentin, joka renderöidään moduulin latautuessa.
6. Käynnistä sovellukset:
Käynnistä sekä isäntä- että etäsovellus komennolla npm start (tai haluamallasi tavalla). Varmista, että etäsovellus on käynnissä *ennen* isäntäsovellusta.
Sinun pitäisi nyt nähdä etä-widget renderöitynä isäntäsovelluksen sisällä.
Edistyneet Module Federation -tekniikat
Perusasetusten lisäksi Module Federation tarjoaa useita edistyneitä tekniikoita hienostuneiden micro-frontend-arkkitehtuurien rakentamiseen.
1. Versioiden hallinta ja jakaminen:
Jaettujen riippuvuuksien tehokas käsittely on ratkaisevan tärkeää vakauden ylläpitämiseksi ja ristiriitojen välttämiseksi. Module Federation tarjoaa mekanismeja versioalueiden ja jaettujen moduulien singleton-instanssien määrittämiseen. Käyttämällä Webpack-määritysten shared-ominaisuutta voit hallita, miten jaettuja moduuleja ladataan ja hallinnoidaan.
Esimerkki:
shared: {
react: { singleton: true, requiredVersion: '^17.0.0' },
'react-dom': { singleton: true, requiredVersion: '^17.0.0' },
lodash: { eager: true, version: '4.17.21' }
}
singleton: true: Varmistaa, että moduulista ladataan vain yksi instanssi, mikä estää päällekkäisyyksiä ja pienentää paketin kokoa. Tämä on erityisen tärkeää Reactin ja ReactDOMin kaltaisille kirjastoille.requiredVersion: Määrittää versioalueen, jonka sovellus vaatii. Webpack yrittää ladata yhteensopivan version moduulista.eager: true: Lataa moduulin välittömästi laiskalatauksen sijaan. Tämä voi parantaa suorituskykyä joissakin tapauksissa, mutta voi myös kasvattaa alkuperäistä paketin kokoa.
2. Dynaaminen Module Federation:
Sen sijaan, että kovakoodaisit etäsovellusten URL-osoitteet, voit ladata ne dynaamisesti määritystiedostosta tai API-päätepisteestä. Tämä mahdollistaa micro-frontend-arkkitehtuurin päivittämisen ilman isäntäsovelluksen uudelleenjulkaisua.
Esimerkki:
Luo määritystiedosto (esim. remote-config.json), joka sisältää etäsovellusten URL-osoitteet:
{
"RemoteApp": "http://localhost:3001/remoteEntry.js",
"AnotherRemoteApp": "http://localhost:3002/remoteEntry.js"
}
Nouda määritystiedosto isäntäsovelluksessa ja luo dynaamisesti remotes-objekti:
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const path = require('path');
const fs = require('fs');
module.exports = {
// ... muut määritykset
plugins: [
new ModuleFederationPlugin({
name: 'Host',
filename: 'remoteEntry.js',
remotes: new Promise(resolve => {
fs.readFile(path.resolve(__dirname, 'remote-config.json'), (err, data) => {
if (err) {
console.error('Virhe luettaessa remote-config.json-tiedostoa:', err);
resolve({});
} else {
try {
const remotesConfig = JSON.parse(data.toString());
resolve(remotesConfig);
} catch (parseError) {
console.error('Virhe jäsennettäessä remote-config.json-tiedostoa:', parseError);
resolve({});
}
}
});
}),
shared: {
react: { singleton: true, requiredVersion: '^17.0.0' },
'react-dom': { singleton: true, requiredVersion: '^17.0.0' },
// Lisää muut jaetut riippuvuudet tähän
},
}),
// ... muut lisäosat
],
};
Tärkeä huomautus: Harkitse vankemman menetelmän käyttämistä etämääritysten noutamiseen tuotantoympäristössä, kuten API-päätepistettä tai erillistä konfiguraatiopalvelua. Yllä oleva esimerkki käyttää fs.readFile-funktiota yksinkertaisuuden vuoksi, mutta se ei yleensä sovellu tuotantojulkaisuihin.
3. Mukautetut latausstrategiat:
Module Federation antaa sinun mukauttaa, miten etämoduulit ladataan. Voit toteuttaa mukautettuja latausstrategioita suorituskyvyn optimoimiseksi tai erityistilanteiden käsittelemiseksi, kuten moduulien lataaminen CDN:stä tai service workerin käyttö.
Webpack paljastaa hookeja, joiden avulla voit siepata ja muokata moduulien latausprosessia. Tämä mahdollistaa hienojakoisen hallinnan siitä, miten etämoduulit noudetaan ja alustetaan.
4. CSS:n ja tyylien käsittely:
CSS:n ja tyylien jakaminen micro-frontendien välillä voi olla hankalaa. Module Federation tukee erilaisia lähestymistapoja tyylien käsittelyyn, mukaan lukien:
- CSS-moduulit: Käytä CSS-moduuleja tyylien kapselointiin kunkin micro-frontendin sisällä, mikä estää ristiriitoja ja varmistaa yhtenäisyyden.
- Styled Components: Hyödynnä styled-komponentteja tai muita CSS-in-JS-kirjastoja tyylien hallintaan itse komponenteissa.
- Globaalit tyylit: Lataa globaalit tyylit jaetusta kirjastosta tai CDN:stä. Ole varovainen tämän lähestymistavan kanssa, koska se voi johtaa ristiriitoihin, jos tyylejä ei ole nimetty oikein omilla nimiavaruuksillaan.
Esimerkki CSS-moduulien käytöstä:
Määritä Webpack käyttämään CSS-moduuleja:
module: {
rules: [
{
test: /\.module\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: {
localIdentName: '[name]__[local]--[hash:base64:5]',
},
importLoaders: 1,
},
},
'postcss-loader',
],
},
// ... muut säännöt
],
}
Tuo CSS-moduulit komponenteissasi:
import React from 'react';
import styles from './Widget.module.css';
const Widget = () => {
return (
Etä-Widget
Tämä on widget RemoteApp-sovelluksesta.
);
};
export default Widget;
5. Kommunikaatio Micro-Frontendien välillä:
Micro-frontendien on usein kommunikoitava keskenään vaihtaakseen dataa tai käynnistääkseen toimintoja. Tähän on useita tapoja:
- Jaetut tapahtumat (Events): Käytä globaalia tapahtumaväylää (event bus) tapahtumien julkaisemiseen ja tilaamiseen. Tämä mahdollistaa micro-frontendien asynkronisen kommunikaation ilman suoria riippuvuuksia.
- Mukautetut tapahtumat (Custom Events): Hyödynnä mukautettuja DOM-tapahtumia kommunikaatioon saman sivun sisällä olevien micro-frontendien välillä.
- Jaettu tilanhallinta: Käytä jaettua tilanhallintakirjastoa (esim. Redux, Zustand) tilan keskittämiseen ja datan jakamisen helpottamiseen.
- Suorat moduulituonnit: Jos micro-frontendit ovat tiiviisti kytkettyjä, voit tuoda moduuleja suoraan toisistaan käyttämällä Module Federationia. Tätä lähestymistapaa tulisi kuitenkin käyttää säästeliäästi, jotta vältetään riippuvuuksien luominen, jotka heikentävät micro-frontendien etuja.
- API:t ja palvelut: Micro-frontendit voivat kommunikoida keskenään API-rajapintojen ja palveluiden kautta, mikä mahdollistaa löyhän kytkennän ja suuremman joustavuuden. Tämä on erityisen hyödyllistä, kun micro-frontendit on julkaistu eri domaineihin tai niillä on erilaiset tietoturvavaatimukset.
Module Federationin käytön edut Micro-Frontendeissä
- Parempi skaalautuvuus: Micro-frontendejä voidaan skaalata itsenäisesti, mikä mahdollistaa resurssien kohdentamisen sinne, missä niitä eniten tarvitaan.
- Parempi ylläpidettävyys: Pienempiä koodikantoja on helpompi ymmärtää ja ylläpitää, mikä vähentää bugien riskiä ja parantaa kehittäjien tuottavuutta.
- Nopeammat julkaisusyklit: Micro-frontendit voidaan julkaista itsenäisesti, mikä mahdollistaa nopeammat iteraatiosyklit ja uusien ominaisuuksien nopeamman julkaisun.
- Teknologinen monimuotoisuus: Tiimit voivat valita tarpeisiinsa parhaiten sopivat teknologiat ja viitekehykset, mikä edistää innovaatiota ja mahdollistaa erikoisosaamisen käytön.
- Lisääntynyt tiimien autonomia: Jokainen micro-frontend on omistettu omalle tiimilleen, mikä edistää omistajuutta ja vastuullisuutta.
- Yksinkertaistettu perehdytys: Uudet kehittäjät pääsevät nopeasti vauhtiin pienempien ja helpommin hallittavien koodikantojen parissa.
Module Federationin käytön haasteet
- Lisääntynyt monimutkaisuus: Micro-frontend-arkkitehtuurit voivat olla monimutkaisempia kuin perinteiset monoliittiset arkkitehtuurit, mikä vaatii huolellista suunnittelua ja koordinointia.
- Jaettujen riippuvuuksien hallinta: Jaettujen riippuvuuksien hallinta voi olla haastavaa, erityisesti kun eri micro-frontendit käyttävät saman kirjaston eri versioita.
- Kommunikaation aiheuttama yleiskuorma: Micro-frontendien välinen kommunikaatio voi aiheuttaa yleiskuormaa ja viivettä.
- Integraatiotestaus: Micro-frontendien integraation testaaminen voi olla monimutkaisempaa kuin monoliittisen sovelluksen testaaminen.
- Alkuasennuksen vaatima työ: Module Federationin konfigurointi ja alkuperäisen infrastruktuurin pystyttäminen voi vaatia merkittäviä ponnisteluja.
Tosielämän esimerkkejä ja käyttötapauksia
Yhä useammat yritykset käyttävät Module Federationia suurten ja monimutkaisten web-sovellusten rakentamiseen. Tässä on joitakin tosielämän esimerkkejä ja käyttötapauksia:
- Verkkokauppa-alustat: Suuret verkkokauppa-alustat käyttävät usein micro-frontendejä hallitakseen verkkosivuston eri osia, kuten tuotekatalogia, ostoskoria ja kassaprosessia. Esimerkiksi saksalainen vähittäiskauppias voi käyttää erillistä micro-frontendiä tuotteiden näyttämiseen saksaksi, kun taas ranskalainen kauppias käyttää eri micro-frontendiä ranskalaisille tuotteille, molemmat integroituna yhteen isäntäsovellukseen.
- Rahoituslaitokset: Pankit ja rahoituslaitokset käyttävät micro-frontendejä rakentaakseen monimutkaisia pankkisovelluksia, kuten verkkopankkiportaaleja, sijoitusalustoja ja kaupankäyntijärjestelmiä. Globaalilla pankilla voi olla tiimejä eri maissa kehittämässä micro-frontendejä eri alueille, joista kukin on räätälöity paikallisiin säännöksiin ja asiakkaiden mieltymyksiin.
- Sisällönhallintajärjestelmät (CMS): CMS-alustat voivat käyttää micro-frontendejä antaakseen käyttäjille mahdollisuuden muokata verkkosivustojensa ulkoasua ja toiminnallisuutta. Esimerkiksi kanadalainen CMS-palveluita tarjoava yritys voi antaa käyttäjien lisätä tai poistaa erilaisia micro-frontendejä (widgettejä) verkkosivustolleen sen toiminnallisuuden mukauttamiseksi.
- Kojelaudat ja analytiikka-alustat: Micro-frontendit soveltuvat hyvin kojelautojen ja analytiikka-alustojen rakentamiseen, joihin eri tiimit voivat tuottaa erilaisia widgettejä ja visualisointeja.
- Terveydenhuollon sovellukset: Terveydenhuollon tarjoajat käyttävät micro-frontendejä potilasportaalien, sähköisten potilastietojärjestelmien (EHR) ja etälääketieteen alustojen rakentamiseen.
Parhaat käytännöt Module Federationin toteuttamiseen
Varmistaaksesi Module Federation -toteutuksesi onnistumisen, noudata näitä parhaita käytäntöjä:
- Suunnittele huolellisesti: Ennen aloittamista, suunnittele micro-frontend-arkkitehtuurisi huolellisesti ja määrittele selkeät rajat eri sovellusten välille.
- Luo selkeät viestintäkanavat: Luo selkeät viestintäkanavat eri micro-frontendien vastuulla olevien tiimien välille.
- Automatisoi julkaisu: Automatisoi julkaisuprosessi varmistaaksesi, että micro-frontendit voidaan julkaista nopeasti ja luotettavasti.
- Seuraa suorituskykyä: Seuraa micro-frontend-arkkitehtuurisi suorituskykyä tunnistaaksesi ja korjataksesi mahdolliset pullonkaulat.
- Toteuta vankka virheidenkäsittely: Toteuta vankka virheidenkäsittely estääksesi ketjureaktioina tapahtuvia virheitä ja varmistaaksesi sovelluksen vikasietoisuuden.
- Käytä yhtenäistä koodityyliä: Vaadi yhtenäistä koodityyliä kaikissa micro-frontendeissä ylläpidettävyyden parantamiseksi.
- Dokumentoi kaikki: Dokumentoi arkkitehtuurisi, riippuvuudet ja viestintäprotokollat varmistaaksesi, että järjestelmä on hyvin ymmärretty ja ylläpidettävä.
- Harkitse tietoturvavaikutuksia: Harkitse huolellisesti micro-frontend-arkkitehtuurisi tietoturvavaikutuksia ja toteuta asianmukaiset turvatoimet. Varmista, että noudatetaan maailmanlaajuisia tietosuoja-asetuksia, kuten GDPR ja CCPA.
Yhteenveto
JavaScript Module Federation ja Webpack 5 tarjoavat tehokkaan ja joustavan tavan rakentaa micro-frontend-arkkitehtuureja. Pilkkomalla suuret sovellukset pienemmiksi, itsenäisesti julkaistaviksi yksiköiksi voit parantaa skaalautuvuutta, ylläpidettävyyttä ja tiimien autonomiaa. Vaikka micro-frontendien toteuttamiseen liittyy haasteita, hyödyt usein ylittävät kustannukset, erityisesti monimutkaisissa web-sovelluksissa. Noudattamalla tässä oppaassa esitettyjä parhaita käytäntöjä voit onnistuneesti hyödyntää Module Federationia rakentaaksesi vakaita ja skaalautuvia micro-frontend-arkkitehtuureja, jotka vastaavat organisaatiosi ja käyttäjien tarpeita maailmanlaajuisesti.